home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS03.ADF
/
C
/
skewb.c
< prev
next >
Wrap
Text File
|
1986-04-02
|
19KB
|
693 lines
/***************************************************************************
* *
* SKEWB by Raymond S. Brand *
* *
***************************************************************************/
/***************************************************************************
* *
* The weird looking constants are because this program is actually a *
* 'C' version written for the Amiga of the original Pascal program that *
* was written for a Tektronics 4113 Color Raster Display Terminal. *
* *
* RSBX *
* *
***************************************************************************/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#define MAXMODE 1 /* Highres-Interlace ( 640 x 400 ) */
#define TALLMODE 2 /* Interlace ( 320 x 400 ) */
#define WIDEMODE 3 /* Highres ( 640 x 200 ) */
#define MINMODE 4 /* ( 320 x 200 ) */
#define DEFAULTMODE MAXMODE
#ifndef DISPLAYMODE
#define DISPLAYMODE DEFAULTMODE
#endif
#if (DISPLAYMODE == MAXMODE)
#define DISPLAYWIDTH 640
#define DISPLAYHEIGHT 400
#define DISPLAYVIEWMODE HIRES | LACE
#endif
#if (DISPLAYMODE == TALLMODE)
#define DISPLAYWIDTH 320
#define DISPLAYHEIGHT 400
#define DISPLAYVIEWMODE LACE
#endif
#if (DISPLAYMODE == WIDEMODE)
#define DISPLAYWIDTH 640
#define DISPLAYHEIGHT 200
#define DISPLAYVIEWMODE HIRES
#endif
#if (DISPLAYMODE == MINMODE)
#define DISPLAYWIDTH 320
#define DISPLAYHEIGHT 200
#define DISPLAYVIEWMODE NULL
#endif
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
#define INTUITION_REV 29
#define GRAPHICS_REV 29
struct TextAttr MyFont =
{
"topaz.font", /* Font Name */
TOPAZ_SIXTY, /* Font Height */
FS_NORMAL, /* Style */
FPF_ROMFONT, /* Preferences */
};
struct NewScreen NewScreen =
{
0, /* LeftEdge */
0, /* TopEdge */
DISPLAYWIDTH, /* Width */
DISPLAYHEIGHT, /* Height */
4, /* Depth (4 planes = 16 colors) */
1, /* DetailPen */
2, /* BlockPen */
DISPLAYVIEWMODE, /* ViewModes */
CUSTOMSCREEN, /* Type */
&MyFont, /* *Font */
"Skewb by Raymond S. Brand", /* *DefaultTitle */
NULL, /* *Gadgets */
NULL, /* *CustomBitMap */
};
struct Screen *Screen;
struct NewWindow NewWindow;
struct Window *Window1;
struct Window *Window2;
struct Verticies
{
SHORT X;
SHORT Y;
};
struct TileRecord
{
SHORT Color;
struct Verticies TileVert[4];
};
struct TileRecord Tiles[6][11][11];
WORD areaverts[25];
struct TmpRas arearas;
struct AreaInfo areadata;
VOID OpenDisplay();
VOID CloseDisplay();
VOID SetColors();
SHORT Order();
SHORT Sign();
SHORT CubeCorr_to_ArrayCorr();
SHORT ArrayCorr_to_CubeCorr();
SHORT Tile();
VOID ChangeDisplay();
VOID CreateCube();
VOID RotateSlice();
VOID MoveSlice();
VOID ChangeTile();
VOID InitSkewb();
SHORT Norm_to_Axis();
SHORT Norm_to_Face();
VOID Swap();
VOID RotateVector();
VOID RotatePlane();
VOID RotateFace();
VOID RotateSlice();
SHORT Cube_Order;
#define Cos1 0.7071067811865
#define Sin1 -0.7071067811865
#define Cos2 0.8164965809282
#define Sin2 0.57735026919
#define Distance -0.125
DOUBLE M1X = ( ( 700.0 / 4096.0 ) * DISPLAYWIDTH );
DOUBLE M1Y = ( ( 700.0 / 3048.0 ) * DISPLAYHEIGHT );
DOUBLE M2X = -( ( 200.0 / 4096.0 ) * DISPLAYWIDTH );
DOUBLE M2Y = -( ( 200.0 / 3048.0 ) * DISPLAYHEIGHT );
SHORT X1 = ( ( 1648.0 / 4096.0 ) * DISPLAYWIDTH );
SHORT Y1 = ( ( 1606.0 / 3048.0 ) * DISPLAYHEIGHT );
SHORT Z1 = 1;
SHORT X2 = ( ( 462.0 / 4096.0 ) * DISPLAYWIDTH );
SHORT Y2 = ( ( 2618.0 / 3048.0 ) * DISPLAYHEIGHT );
SHORT Z2 = -1;
SHORT X3 = ( ( 2836.0 / 4096.0 ) * DISPLAYWIDTH );
SHORT Y3 = ( ( 2608.0 / 3048.0 ) * DISPLAYHEIGHT );
SHORT Z3 = 1;
main ()
{
struct IntuiMessage *message;
ULONG class;
USHORT code;
SHORT GoodBye;
SHORT Axis;
SHORT Plane;
OpenDisplay();
InitSkewb();
GoodBye = FALSE;
Axis = 1;
Plane = 0;
FOREVER
{
while (message = (struct IntuiMessage *)GetMsg(Window2->UserPort))
{
class = message->Class;
code = message->Code;
ReplyMsg(message);
if(class == CLOSEWINDOW)
{
GoodBye = TRUE;
break;
};
if(class == MOUSEBUTTONS)
{
if(code == SELECTDOWN)
{
Cube_Order = (Cube_Order - 1) % 9 + 2;
CreateCube();
Plane = 0;
Axis = 1;
};
};
};
if(GoodBye) break;
Delay(25);
RotateSlice(Axis,Plane,1);
Axis += Sign(Axis);
if(Axis > 3)
Axis = -1;
if(Axis < -3)
{
Axis = 1;
Plane = (Plane + 1) % Cube_Order;
};
};
CloseDisplay();
exit(TRUE);
}
VOID OpenDisplay()
{
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library",INTUITION_REV);
if (IntuitionBase == NULL) exit(20);
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
if (GfxBase == NULL) exit(20);
if ((Screen = (struct Screen *)OpenScreen(&NewScreen)) == NULL)
exit(20);
ShowTitle(Screen,FALSE); /* Put the Screen title behind any
backdrop window that may exist */
/* Define Vanilla backdrop window for drawing onto */
NewWindow.LeftEdge = 0;
NewWindow.TopEdge = 0;
NewWindow.Width = DISPLAYWIDTH;
NewWindow.Height = DISPLAYHEIGHT;
NewWindow.DetailPen = 1;
NewWindow.BlockPen = 2;
NewWindow.IDCMPFlags = NULL;
NewWindow.Flags = SMART_REFRESH | BACKDROP | ACTIVATE;
NewWindow.FirstGadget = NULL;
NewWindow.CheckMark = NULL;
NewWindow.Title = NULL;
NewWindow.Screen = Screen;
NewWindow.BitMap = NULL;
NewWindow.MinWidth = DISPLAYWIDTH;
NewWindow.MinHeight = DISPLAYHEIGHT;
NewWindow.MaxWidth = DISPLAYWIDTH;
NewWindow.MaxHeight = DISPLAYHEIGHT;
NewWindow.Type = CUSTOMSCREEN;
if ((Window1 = (struct Window *)OpenWindow(&NewWindow)) == NULL)
{
CloseScreen(Screen);
exit(20);
};
/* Define a window with a close gadget so that we can exit this program */
NewWindow.LeftEdge = DISPLAYWIDTH - 100;
NewWindow.TopEdge = DISPLAYHEIGHT - 50;
NewWindow.Width = 100;
NewWindow.Height = 50;
NewWindow.DetailPen = 1;
NewWindow.BlockPen = 2;
NewWindow.IDCMPFlags = CLOSEWINDOW | MOUSEBUTTONS;
NewWindow.Flags = SMART_REFRESH | WINDOWDRAG | WINDOWCLOSE;
NewWindow.FirstGadget = NULL;
NewWindow.CheckMark = NULL;
NewWindow.Title = "Skewb";
NewWindow.Screen = Screen;
NewWindow.BitMap = NULL;
NewWindow.MinWidth = 100;
NewWindow.MinHeight = 50;
NewWindow.MaxWidth = 100;
NewWindow.MaxHeight = 50;
NewWindow.Type = CUSTOMSCREEN;
if ((Window2 = (struct Window *)OpenWindow(&NewWindow)) == NULL)
{
CloseWindow(Window1);
CloseScreen(Screen);
exit(20);
};
SetColors();
InitArea(&areadata,areaverts,10);
Window1->RPort->AreaInfo=&areadata;
if((arearas.RasPtr = (BYTE *)AllocRaster(DISPLAYWIDTH,DISPLAYHEIGHT)) == NULL)
{
CloseWindow(Window2);
CloseWindow(Window1);
CloseScreen(Screen);
exit(20);
};
arearas.Size=RASSIZE(DISPLAYWIDTH,DISPLAYHEIGHT);
Window1->RPort->TmpRas=&arearas;
SetRast(Window1->RPort,0);
SetOPen(Window1->RPort,15);
}
VOID CloseDisplay()
{
FreeRaster(arearas.RasPtr,DISPLAYWIDTH,DISPLAYHEIGHT);
CloseWindow(Window1);
CloseWindow(Window2);
CloseScreen(Screen);
}
VOID SetColors()
{
SetRGB4(&Screen->ViewPort, 0, 8, 8, 8); /* background */
SetRGB4(&Screen->ViewPort, 1,15,15,15); /* detail */
SetRGB4(&Screen->ViewPort, 2, 0, 0, 0); /* block */
SetRGB4(&Screen->ViewPort, 3, 6, 6, 6);
SetRGB4(&Screen->ViewPort, 4, 6, 6, 6);
SetRGB4(&Screen->ViewPort, 5, 6, 6, 6);
SetRGB4(&Screen->ViewPort, 6, 6, 6, 6);
SetRGB4(&Screen->ViewPort, 7, 6, 6, 6);
SetRGB4(&Screen->ViewPort, 8,15, 0, 0); /* red */
SetRGB4(&Screen->ViewPort, 9, 0,15, 0); /* green */
SetRGB4(&Screen->ViewPort,10, 0, 0,15); /* blue */
SetRGB4(&Screen->ViewPort,11,15,15,15); /* white */
SetRGB4(&Screen->ViewPort,12,15, 9, 0); /* orange */
SetRGB4(&Screen->ViewPort,13,15,15, 0); /* yellow */
SetRGB4(&Screen->ViewPort,14, 6, 6, 6);
SetRGB4(&Screen->ViewPort,15, 0, 0, 0); /* outline */
}
SHORT Order()
{
return(Cube_Order);
}
SHORT Sign(number)
SHORT number;
{
if (number == 0) return(0);
if (number > 0) return(1);
return(-1);
}
SHORT CubeCorr_to_ArrayCorr(Cube_Corr)
SHORT Cube_Corr;
{
if ((Cube_Order % 2) == 0) /* even */
return( (SHORT)( Cube_Order / 2 - Cube_Corr
- ( Cube_Order + 2 - 2 * Cube_Corr ) / ( Cube_Order + 2 ) ) );
else /* odd */
return( (SHORT)( ( Cube_Order - 1 - 2 * Cube_Corr ) / 2 ) );
}
SHORT ArrayCorr_to_CubeCorr(Array_Corr)
SHORT Array_Corr;
{
if ((Cube_Order % 2) == 0) /* even */
return( (SHORT)( Cube_Order / 2 - Array_Corr
- ( 2 * Array_Corr + 2 ) / ( Cube_Order + 1 ) ) );
else /* odd */
return( (SHORT)( ( Cube_Order - 1 - 2 * Array_Corr ) / 2 ) );
}
SHORT Tile()
{
}
VOID ChangeTile(tileptr,x,y,z)
struct TileRecord *tileptr;
SHORT x;
SHORT y;
SHORT z;
{
SHORT i;
SetAPen(Window1->RPort,tileptr->Color+8);
AreaMove(Window1->RPort,tileptr->TileVert[0].X*z+x,
DISPLAYHEIGHT - (tileptr->TileVert[0].Y*z+y));
for (i = 1; i < 4; i++)
AreaDraw(Window1->RPort,tileptr->TileVert[i].X*z+x,
DISPLAYHEIGHT - (tileptr->TileVert[i].Y*z+y));
AreaEnd(Window1->RPort);
}
VOID ChangeDisplay(face,x,y)
SHORT face;
SHORT x;
SHORT y;
{
struct TileRecord *TileData;
TileData = &Tiles[face][x][y]; /* should point to the tile structure */
if (face < 3)
ChangeTile(TileData,X1,Y1,Z1);
else
{
ChangeTile(TileData,X2,Y2,Z2);
ChangeTile(TileData,X3,Y3,Z3);
};
}
VOID CreateCube()
{
SHORT Direction;
SHORT Plane;
SHORT Index1;
SHORT Index2;
SHORT Index3;
SHORT Index4;
DOUBLE Temp;
struct {
DOUBLE X;
DOUBLE Y;
} Matrix[11][11];
struct TileRecord *withtile;
DOUBLE Vector[3];
DOUBLE MultX;
DOUBLE MultY;
MultX = M1X;
MultY = M1Y;
for(Direction=0;Direction<2;Direction++)
{
for(Plane=0;Plane<3;Plane++)
{
for(Index1=0;Index1<=Cube_Order;Index1++)
{
for(Index2=0;Index2<=Cube_Order;Index2++)
{
Vector[Plane]=(1.0 - 2.0 * Direction);
Vector[(Plane+1) % 3]=((Cube_Order - 2.0 * Index1) / Cube_Order);
Vector[(Plane+2) % 3]=((Cube_Order - 2.0 * Index2) / Cube_Order);
Temp=(1.0 + Distance * (1.0 - 2.0 * Direction)
* ( -Vector[0] * Sin1 * Cos2
+Vector[1] * Sin2
+Vector[2] * Cos1 * Cos2 ));
Matrix[Index1][Index2].X=( Vector[0] * Cos1
+Vector[2] * Sin1 ) / Temp;
Matrix[Index1][Index2].Y=( Vector[0] * Sin1 * Sin2
+Vector[1] * Cos2
-Vector[2] * Cos1 * Sin2 ) / Temp;
}
};
for(Index1=0;Index1<Cube_Order;Index1++)
{
for(Index2=0;Index2<Cube_Order;Index2++)
{
withtile = &Tiles[Plane + 3 * Direction][Index1][Index2];
withtile->Color=Plane + 3 * Direction;
for(Index3=0;Index3<2;Index3++)
{
for(Index4=0;Index4<2;Index4++)
{
withtile->TileVert[Index3 * 2 + Index4].X
= (Matrix[Index1 + Index3]
[Index2 + Index3 + Index4
-2 * Index3 * Index4].X
* (1.0 - 2.0 * Direction) * MultX);
withtile->TileVert[Index3 * 2 + Index4].Y
= (Matrix[Index1 + Index3]
[Index2 + Index3 + Index4
-2 * Index3 * Index4].Y * MultY);
};
};
ChangeDisplay(Plane + 3 * Direction,Index1,Index2);
};
};
};
MultX = M2X;
MultY = M2Y;
};
}
VOID InitSkewb()
{
Cube_Order = 2;
CreateCube();
}
SHORT Norm_to_Axis(Vector)
SHORT *Vector;
{
SHORT Temp;
SHORT Index;
Temp = 0;
for(Index=0 ; Index<3 ; Index++)
Temp += Sign(Vector[Index]) * (Index + 1);
return(Temp);
}
SHORT Norm_to_Face(Vector)
SHORT *Vector;
{
SHORT Temp;
Temp = Norm_to_Axis(Vector);
if(Temp<0)
Temp = 3 - Temp;
Temp -= 1;
return(Temp);
}
VOID Swap_Short(a,b)
SHORT *a;
SHORT *b;
{
SHORT Temp;
Temp = *a;
*a = *b;
*b = Temp;
}
VOID RotateVector(Vector,Axis,Direction)
SHORT *Vector;
SHORT Axis;
SHORT Direction;
{
SHORT Rotate;
Rotate = Sign(Axis) * Sign(Direction);
Axis = Sign(Axis) * Axis;
Swap_Short(&Vector[Axis % 3],&Vector[(Axis + 1) % 3]);
if(Rotate>0)
Vector[(Axis + 1) % 3] *= -1;
else
Vector[Axis % 3] *= -1;
}
VOID RotatePlane(Axis,Plane,Direction)
SHORT Axis;
SHORT Plane;
SHORT Direction;
{
SHORT Norm[3];
SHORT Tile[3];
SHORT n;
SHORT x;
SHORT y;
SHORT z;
SHORT Color;
SHORT Index1;
SHORT Index2;
x = Sign(Axis) * Axis - 1;
y = (x + 1) % 3;
z = (y + 1) % 3;
Norm[x] = 0;
Norm[y] = ArrayCorr_to_CubeCorr(0);
Norm[z] = 0;
Tile[x] = Sign(Axis) * ArrayCorr_to_CubeCorr(Plane);
for(Index1=0 ; Index1<Cube_Order ; Index1++)
{
x = Norm_to_Axis(&Norm);
x = Sign(x) * x - 1;
y = (x + 1) % 3;
z = (y + 1) % 3;
Tile[x] = Norm[x];
Tile[y] = ArrayCorr_to_CubeCorr(Index1);
Color = Tiles[Norm_to_Face(&Norm)]
[CubeCorr_to_ArrayCorr(Tile[y])]
[CubeCorr_to_ArrayCorr(Tile[z])].Color;
for(Index2=0 ; Index2<4 ; Index2++)
{
RotateVector(&Norm,Axis,Direction);
RotateVector(&Tile,Axis,Direction);
x = Norm_to_Axis(&Norm);
x = Sign(x) * x - 1;
y = CubeCorr_to_ArrayCorr(Tile[(x + 1) % 3]);
z = CubeCorr_to_ArrayCorr(Tile[(x + 2) % 3]);
n = Norm_to_Face(&Norm);
Swap_Short(&Color,&Tiles[n][y][z].Color);
ChangeDisplay(n,y,z);
};
};
}
VOID RotateFace(Axis,Plane,Direction)
SHORT Axis;
SHORT Plane;
SHORT Direction;
{
SHORT Tile[3];
SHORT Color;
SHORT n;
SHORT x;
SHORT y;
SHORT z;
SHORT Index1;
SHORT Index2;
SHORT Index3;
x = Sign(Axis) * Axis - 1;
y = (x + 1) % 3;
z = (y + 1) % 3;
n = Axis * Sign(ArrayCorr_to_CubeCorr(Plane));
if(n<0)
n = 3 - n - 1;
else
n -= 1;
for(Index1=0 ; Index1 < (Cube_Order / 2) ; Index1++)
{
for(Index2=0 ; Index2 <= (Cube_Order - 2 * (Index1 + 1)) ; Index2++)
{
Tile[y] = ArrayCorr_to_CubeCorr(Index1);
Tile[z] = ArrayCorr_to_CubeCorr(Index1 + Index2);
Color = Tiles[n][Index1][Index1 + Index2].Color;
for(Index3=0 ; Index3<4 ; Index3++)
{
RotateVector(&Tile,Axis,Direction);
Swap_Short(&Color,&Tiles[n]
[CubeCorr_to_ArrayCorr(Tile[y])]
[CubeCorr_to_ArrayCorr(Tile[z])].Color);
ChangeDisplay(n,CubeCorr_to_ArrayCorr(Tile[y])
,CubeCorr_to_ArrayCorr(Tile[z]));
};
};
};
}
VOID RotateSlice(Axis,Plane,Displacement)
SHORT Axis;
SHORT Plane;
SHORT Displacement;
{
for( ; Displacement != 0 ; Displacement -= Sign(Displacement))
{
RotatePlane(Axis,Plane,Displacement);
if( (Plane * (Cube_Order - Plane - 1)) == 0 )
RotateFace(Axis,Plane,Displacement);
};
}